package do

import (
	"micro.hotel.server/common"
	"micro.hotel.server/database"
	"micro.hotel.server/models"
)

const (
	DBTable = "vs_hotel"
)

func CreateHotel(hotel *models.VsHotel) error {
	eg := database.GetDB()
	if eg == nil {
		return common.DBNil
	}

	afterID, err := eg.Table(DBTable).Insert(hotel)
	if err != nil {
		return common.DBErr
	}
	if afterID < 1 {
		return common.DBInsertErr
	}

	return nil
}

func DeleteHotel(hotelIDs []uint64) error {
	eg := database.GetDB()
	if eg == nil {
		return common.DBNil
	}

	hotel := &models.VsHotel{}
	afterID, err := eg.Table(DBTable).In("hotel_id", hotelIDs).Delete(hotel)
	if err != nil {
		return err
	}
	if afterID < 1 {
		return common.DBDeleteErr
	}

	return nil
}

func UpdateHotel(hotel *models.VsHotel) error {
	eg := database.GetDB()
	if eg == nil {
		return common.DBNil
	}

	afterID, err := eg.Table(DBTable).ID(hotel.HotelId).Update(hotel)
	if err != nil {
		return err
	}
	if afterID < 1 {
		return common.DBErr
	}

	return nil
}

func BatchHotelInfo(hotelIDs []uint64) ([]*models.VsHotel, error) {
	eg := database.GetDB()
	if eg == nil {
		return nil, common.DBNil
	}

	hotels := make([]*models.VsHotel, 0)
	err := eg.Table(DBTable).In("hotel_id", hotelIDs).Find(hotels)
	if err != nil {
		return nil, err
	}

	return hotels, nil
}

func SearchHotel(req *models.SearchParams) ([]*models.VsHotel, int64, error) {
	eg := database.GetDB()
	if eg == nil {
		return nil, 0, common.DBNil
	}

	session := eg.NewSession()

	hotels := make([]*models.VsHotel, 0)

	if req.HotelName != "" {
		session.Where("hotel_name = ?", req.HotelName)
	}
	if req.HotelTitle != "" {
		session.Where("hotel_title = ?", req.HotelTitle)
	}
	if req.HotelPhone != "" {
		session.Where("hotel_phone = ?", req.HotelPhone)
	}
	if req.HotelAddress != "" {
		session.Where("hotel_address = ?", req.HotelAddress)
	}
	if req.HotelType != "" {
		session.Where("hotel_type = ?", req.HotelType)
	}
	if req.AreaID > 0 {
		session.Where("area_id = ?", req.AreaID)
	}
	if req.BusinessCircleID > 0 {
		session.Where("business_circle_id = ?", req.BusinessCircleID)
	}
	if req.Score > 0 {
		session.Where("score >= ?", req.Score)
	}
	session.Limit(int(req.Limit), int(req.Offset))

	count, err := session.Table(DBTable).FindAndCount(hotels)
	if err != nil {
		return nil, 0, err
	}

	return hotels, count, nil
}

func Recommend(longitude, latitude float32, limit, offset uint32) ([]*models.VsHotel, int64, error) {
	eg := database.GetDB()
	if eg == nil {
		return nil, 0, common.DBNil
	}

	hotels := make([]*models.VsHotel, 0)

	sql := "SELECT * FROM " +
		"(SELECT*, ROUND(6378.138*2*ASIN (SQRT(POW(SIN((?*PI()/180-?*PI()/180)/2),2)+COS(?*PI()/180)*COS(latitude*PI()/180)*POW(SIN((?*PI()/180-longitude*PI()/180)/2),2)))*1000) AS distance " +
		"FROM vs_area ORDER BY distance ASC) AS t WHERE t.distance< ?"

	count, err := eg.SQL(sql, latitude, latitude, longitude, 10000).FindAndCount(hotels)
	if err != nil {
		return nil, 0, err
	}

	return hotels, count, nil
}
